我們這次要多下載一個套件
npm i axios-mock-adapter
這個套件的用途呢,是模擬axios發送api
首先在describe 裡用MockAdapter 創在一個mock讓我們之後可以做get、post等請求
describe("useFetch", () => { 
const mock = new MockAdapter(axios);
  // 每次測試完成後重置 mock
  afterEach(() => {
    mock.reset();
  });
onGet 是模擬get請求
onPost 是模擬post情球
reply就像是後端的res.send回來的result ,第一個參數是status,第二的是data
waitFor 會等待異步操作完成
toEqual 與 toBe 差別在toEqual可以判斷物件內容是否一樣,因為物件傳址的關係,toBe比較物件都會回傳false,toEqual就是來解決這個問題的
剩下大部分都跟前面我們教過的一樣
import { renderHook, waitFor } from "@testing-library/react";
import MockAdapter from "axios-mock-adapter";
import axios from "axios";
import { useFetchAPI } from "../src"; // 請根據你的目錄結構調整這個 import 路徑
describe("useFetch", () => {
  const mock = new MockAdapter(axios);
  // 每次測試完成後重置 mock
  afterEach(() => {
    mock.reset();
  });
  // 測試成功狀態
  it("成功取得資料", async () => {
    const mockData = { foo: "bar" };
    // 當 GET /api/test 被呼叫時,回傳 mockData
    mock.onGet("/api/test").reply(200, mockData);
    // 執行 hook
    const { result } = renderHook(() => useFetchAPI("/api/test"));
    // 初始狀態應為 loading
    expect(result.current.loading).toBe(true);
    // 等待異步操作完成
    await waitFor(() => {
      // 驗證結果
      expect(result.current.data).toEqual(mockData);
      expect(result.current.loading).toBe(false);
      expect(result.current.error).toBeNull();
    });
  });
  // 測試錯誤狀態
  it("取得資料失敗", async () => {
    // 回傳 500 錯誤
    mock.onGet("/api/test2").reply(500);
    const { result } = renderHook(() => useFetchAPI("/api/test2"));
    expect(result.current.loading).toBeTruthy();
    await waitFor(() => {
      // 驗證結果
      expect(result.current.data).toBeNull();
      expect(result.current.loading).toBe(false);
      expect(result.current.error).not.toBeNull();
    });
  });
  it("can perform POST requests", async () => {
    const url = "http://example.com/data";
    const postData = { key: "value" };
    mock.onPost(url, postData).reply(201);
    const { result } = renderHook(() =>
      useFetchAPI(url, { method: "POST", options: { data: postData } })
    );
    expect(result.current.loading).toBeTruthy();
    await waitFor(() => {
      expect(result.current.loading).toBeFalsy();
      expect(result.current.error).toBeNull();
    });
  });
  // 測試 headers
  it("can send custom headers", async () => {
    const url = "http://example.com/data";
    const headers = { Authorization: "Bearer token" };
    mock.onGet(url, headers).reply(200);
    const { result } = renderHook(() => useFetchAPI(url, { headers }));
    expect(result.current.loading).toBeTruthy();
    await waitFor(() => {
      expect(result.current.loading).toBeFalsy();
      expect(result.current.error).toBeNull();
    });
  });
  // 測試取消請求
  it("can abort a request", async () => {
    const url = "http://example.com/data";
    mock.onGet(url).reply(() => {
      return new Promise((_, reject) => {
        reject;
      });
    });
    const { result, unmount } = renderHook(() => useFetchAPI(url));
    unmount(); // 在請求完成前取消組件
    await waitFor(() => {
      expect(result.current.data).toBeNull();
      expect(result.current.loading).toBe(true); // 仍然在加載
      expect(result.current.error).toBe(null); // 沒有錯誤,因為我們自己取消了請求
    });
  });
  // 測試緩存
  it("can cache requests", async () => {
    const url = "http://example.com/data";
    const responseData = { data: "some data" };
    mock.onGet(url).replyOnce(200, responseData); // 注意:使用 replyOnce,模擬只回覆一次
    // 第一次請求
    const { result, rerender } = renderHook(() => useFetchAPI(url));
    expect(result.current.loading).toBeTruthy();
    await waitFor(() => {
      expect(result.current.data).toEqual(responseData);
    });
    // 觸發第二次請求
    rerender();
    expect(result.current.data).toEqual(responseData); // 應該使用緩存的數據,而不是重新請求
  });
});